package com.student_exam_system.service.impl;

import com.student_exam_system.Util.JwtUtil;
import com.student_exam_system.Util.MybatisUtils;
import com.student_exam_system.Util.SimpleCache;
import com.student_exam_system.dao.UserMapper;
import com.student_exam_system.pojo.LoginUser;
import com.student_exam_system.pojo.Result;
import com.student_exam_system.pojo.User;
import com.student_exam_system.service.UserService;
import org.apache.ibatis.session.SqlSession;import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;
/**
 * @author fire'ge
 */
@Service("userServiceImpl")
public class UserServiceImpl implements UserService {
    private final  UserMapper userMapper;

    private final AuthenticationManager manager;

    private final PasswordEncoder encoder;

    public UserServiceImpl(UserMapper userMapper, AuthenticationManager manager, PasswordEncoder encoder) {
        this.userMapper = userMapper;
        this.manager = manager;
        this.encoder = encoder;
    }



    @Override
    public User getUser(String phoneNum, String password) {
        return userMapper.queryUserByPhoneAndPwd(phoneNum,password);
    }

    @Override
    public User getUserByPhoneNum(String phoneNum) {
        return userMapper.queryUserByUsername(phoneNum);
    }

    @Override
    public Result login(User user) {
        UsernamePasswordAuthenticationToken authenticationToken
                = new UsernamePasswordAuthenticationToken(user.getUserPhoneNum(),user.getUserPassword());
        Authentication authenticate = manager.authenticate(authenticationToken);

        if (authenticate==null){
            throw new RuntimeException("登录失败");
        }

        LoginUser principal = (LoginUser)authenticate.getPrincipal();
        SimpleCache cache = SimpleCache.getInstance();

        cache.putObject("login"+principal.getUser().getUserId(),principal);

        Map<String, String> map = new HashMap<>(5);
        User checkUser = principal.getUser();
        map.put("userId",checkUser.getUserId()+"");
        String token = JwtUtil.getToken(map);
        map.clear();
        map.put("token",token);
        return Result.succ(200,"登陆成功",map);
    }

    @Override
    public int addUser(User user) {
        String userPassword = user.getUserPassword();
        String encode = encoder.encode(userPassword);
        user.setUserPassword(encode);
        return userMapper.addUser(user);
    }

    private final SqlSession session = MybatisUtils.getSession();

    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    @Override
    public User login(String userPhoneNum,String userPassword) {
        User u = null;
        try {
            u = userMapper.selectUser(userPhoneNum,userPassword);
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            session.close();
        }
        return u;
    }

    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    @Override
    public int save(String userPhoneNum,String userPassword,String className) {
        try {

            int classId = userMapper.getClassId(className);
            User u1 = userMapper.selectUser(userPhoneNum,userPassword);
            if (u1 == null) {
                userMapper.insertUser(userPhoneNum,userPassword, classId);
                return 1;
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            MybatisUtils.closeSession(session);
        }
        return 0;
    }
}
